package com.diandian.backend.dingding.data.service;

import com.diandian.backend.dingding.data.domain.DingdingDeptTree;
import com.diandian.backend.dingding.data.domain.DingdingDeptTreeQuery;
import com.diandian.backend.dingding.data.dto.*;
import com.diandian.backend.dingding.data.mapper.DingdingDeptTreeMapper;
import com.diandian.backend.dingding.data.resp.DingdingDeptTreeDetailResp;
import com.diandian.backend.dingding.data.resp.DingdingDeptTreeListQueryResp;
import com.diandian.backend.dingding.data.resp.DingdingDeptTreeQueryResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.diandian.backend.dingding.data.resp.DingdingDeptTreeListResp;

import java.util.*;

@Service
public class DingdingDeptTreeService {

    @Autowired
    private DingdingDeptTreeMapper dingdingDeptTreeMapper;

    public List<DingdingDeptTreeQueryResp> queryTree(DingdingDeptTreeQueryParamDTO dataDTO){

        dataDTO.check();

        List<DingdingDeptTreeQueryResp> resultList = new ArrayList<>();

        // 按照level排序获取所有节点数据
        DingdingDeptTreeListParamDTO treeListParamDTO = new DingdingDeptTreeListParamDTO();
        treeListParamDTO.setBelongEql(dataDTO.getBelong());
        treeListParamDTO.setOrgIdEql(dataDTO.getOrgId());
        treeListParamDTO.setOrgCodeEql(dataDTO.getOrgCode());
        treeListParamDTO.setDeptNodeCodeEql(dataDTO.getDeptNodeCode());
        List<DingdingDeptTreeListQueryResp> treeListResp = getTreeList(treeListParamDTO);
        if(treeListResp == null || treeListResp.size() == 0){
            return resultList;
        }

        // 格式转换
        for (int i = 0; i < treeListResp.size(); i++) {
            DingdingDeptTreeQueryResp item = new DingdingDeptTreeQueryResp();
            item.setId(treeListResp.get(i).getId());
            item.setType(treeListResp.get(i).getType());
            item.setDeptPath(treeListResp.get(i).getDeptPath());
            item.setRemark(treeListResp.get(i).getRemark());
            item.setBelong(treeListResp.get(i).getBelong());
            item.setCreateUserId(treeListResp.get(i).getCreateUserId());
            item.setCreateUserName(treeListResp.get(i).getCreateUserName());
            item.setCreateTime(treeListResp.get(i).getCreateTime());
            item.setOrgId(treeListResp.get(i).getOrgId());
            item.setOrgCode(treeListResp.get(i).getOrgCode());
            item.setUpdateUserId(treeListResp.get(i).getUpdateUserId());
            item.setUpdateUserName(treeListResp.get(i).getUpdateUserName());
            item.setUpdateTime(treeListResp.get(i).getUpdateTime());
            item.setDeptCode(treeListResp.get(i).getDeptCode());
            item.setDeptName(treeListResp.get(i).getDeptName());
            item.setDeptLevel(treeListResp.get(i).getDeptLevel());
            item.setDeptNodeCode(treeListResp.get(i).getDeptNodeCode());
            item.setRemark(treeListResp.get(i).getRemark());
            item.setChildren(new ArrayList<>());
            item.setHasChildren(treeListResp.get(i).getHasChildren());
            item.setDeptNodeName(treeListResp.get(i).getDeptNodeName());
            item.setLevel(treeListResp.get(i).getLevel());
            resultList.add(item);
        }

        return resultList;
    }

    public List<DingdingDeptTreeQueryResp> queryMultiTree(DingdingDeptMultiTreeQueryParamDTO dataDTO){

        dataDTO.check();

        List<DingdingDeptTreeQueryResp> resultList = new ArrayList<>();

        // 如果deptNodeCode不为空，则获取此部门的deptPath用来做前匹配
        String deptNodePath = "";
        if(dataDTO.getDeptNodeCode() != null && !"".equals(dataDTO.getDeptNodeCode())){
            DingdingDeptTreeDetailParamDTO treeDetailParamDTO = new DingdingDeptTreeDetailParamDTO();
            treeDetailParamDTO.setDeptCode(dataDTO.getDeptNodeCode());
            treeDetailParamDTO.setBelong(dataDTO.getBelong());
            DingdingDeptTreeDetailResp deptTreeDetailResp = getDetail(treeDetailParamDTO);
            if(deptTreeDetailResp != null){
                deptNodePath = deptTreeDetailResp.getDeptPath();
            }
        }

        // 按照level排序获取所有节点数据
        DingdingDeptTreeListParamDTO treeListParamDTO = new DingdingDeptTreeListParamDTO();
        treeListParamDTO.setBelongEql(dataDTO.getBelong());
        treeListParamDTO.setOrgIdEql(dataDTO.getOrgId());
        treeListParamDTO.setOrgCodeEql(dataDTO.getOrgCode());
        treeListParamDTO.setDeptPathLike(deptNodePath);
        List<DingdingDeptTreeListQueryResp> treeListResp = getTreeList(treeListParamDTO);
        if(treeListResp == null || treeListResp.size() == 0){
            return resultList;
        }

        // 格式转换
        List<DingdingDeptTreeQueryResp> treeRespList = new ArrayList<>();
        for (int i = 0; i < treeListResp.size(); i++) {
            DingdingDeptTreeQueryResp item = new DingdingDeptTreeQueryResp();
            item.setId(treeListResp.get(i).getId());
            item.setType(treeListResp.get(i).getType());
            item.setDeptPath(treeListResp.get(i).getDeptPath());
            item.setRemark(treeListResp.get(i).getRemark());
            item.setBelong(treeListResp.get(i).getBelong());
            item.setCreateUserId(treeListResp.get(i).getCreateUserId());
            item.setCreateUserName(treeListResp.get(i).getCreateUserName());
            item.setCreateTime(treeListResp.get(i).getCreateTime());
            item.setOrgId(treeListResp.get(i).getOrgId());
            item.setOrgCode(treeListResp.get(i).getOrgCode());
            item.setUpdateUserId(treeListResp.get(i).getUpdateUserId());
            item.setUpdateUserName(treeListResp.get(i).getUpdateUserName());
            item.setUpdateTime(treeListResp.get(i).getUpdateTime());
            item.setDeptCode(treeListResp.get(i).getDeptCode());
            item.setDeptName(treeListResp.get(i).getDeptName());
            item.setDeptLevel(treeListResp.get(i).getDeptLevel());
            item.setDeptNodeCode(treeListResp.get(i).getDeptNodeCode());
            item.setRemark(treeListResp.get(i).getRemark());
            item.setChildren(new ArrayList<>());
            item.setLevel(treeListResp.get(i).getLevel());
            treeRespList.add(item);
        }

        // 按照level进行分组
        Map<String, List<DingdingDeptTreeQueryResp>> tempMap = new LinkedHashMap();
        for (int i = 0; i < treeRespList.size(); i++) {
            DingdingDeptTreeQueryResp item = treeRespList.get(i);
            String nodeLevel = String.valueOf(item.getDeptLevel());
            if(tempMap.get(nodeLevel) == null){
                List<DingdingDeptTreeQueryResp> tempList = new ArrayList<>();
                tempList.add(item);
                tempMap.put(nodeLevel, tempList);
            } else {
                tempMap.get(nodeLevel).add(item);
            }
        }
        int batchCount = tempMap.size();

        // 如果只有一层时，无需进入递归，直接组装返回
        if(batchCount == 1){
            for (Map.Entry<String, List<DingdingDeptTreeQueryResp>> entry : tempMap.entrySet()) {
                resultList.addAll(entry.getValue());
            }
            return resultList;
        }

        // 组装最终返回结果
        for (int i = batchCount + 1; i > 1 ; i--) {

            List<DingdingDeptTreeQueryResp> innerList;
            List<DingdingDeptTreeQueryResp> outerList;
            if(i == batchCount + 1){
                outerList = tempMap.get(String.valueOf(i-1));
                innerList = tempMap.get(String.valueOf(i));
            } else {
                outerList = tempMap.get(String.valueOf(i-1));
                innerList = resultList;
            }
            resultList = makeChildren(outerList, innerList);
        }

        return resultList;
    }

    private List<DingdingDeptTreeQueryResp> makeChildren(List<DingdingDeptTreeQueryResp> parentList, List<DingdingDeptTreeQueryResp> childList){

        if(childList == null || childList.size() == 0){
            return parentList;
        }

        List<DingdingDeptTreeQueryResp> resultList = new ArrayList<>();

        for (int j = 0; j < parentList.size(); j++) {

            DingdingDeptTreeQueryResp jChildren = new DingdingDeptTreeQueryResp();
            jChildren.setId(parentList.get(j).getId());
            jChildren.setType(parentList.get(j).getType());
            jChildren.setRemark(parentList.get(j).getRemark());
            jChildren.setBelong(parentList.get(j).getBelong());
            jChildren.setCreateUserId(parentList.get(j).getCreateUserId());
            jChildren.setCreateUserName(parentList.get(j).getCreateUserName());
            jChildren.setCreateTime(parentList.get(j).getCreateTime());
            jChildren.setOrgId(parentList.get(j).getOrgId());
            jChildren.setOrgCode(parentList.get(j).getOrgCode());
            jChildren.setUpdateUserId(parentList.get(j).getUpdateUserId());
            jChildren.setUpdateUserName(parentList.get(j).getUpdateUserName());
            jChildren.setUpdateTime(parentList.get(j).getUpdateTime());
            jChildren.setDeptCode(parentList.get(j).getDeptCode());
            jChildren.setDeptName(parentList.get(j).getDeptName());
            jChildren.setDeptPath(parentList.get(j).getDeptPath());
            jChildren.setDeptLevel(parentList.get(j).getDeptLevel());
            jChildren.setDeptNodeCode(parentList.get(j).getDeptNodeCode());
            jChildren.setLevel(parentList.get(j).getLevel());

            List<DingdingDeptTreeQueryResp> jChildrenList = new ArrayList<>();
            String nodeCode = parentList.get(j).getDeptCode();
            for (int k = 0; k < childList.size(); k++) {
                String parentNodeCode = childList.get(k).getDeptNodeCode();
                if(parentNodeCode.equals(nodeCode)){
                    DingdingDeptTreeQueryResp kChildren = new DingdingDeptTreeQueryResp();
                    kChildren.setId(childList.get(k).getId());
                    kChildren.setDeptPath(childList.get(k).getDeptPath());
                    kChildren.setRemark(childList.get(k).getRemark());
                    kChildren.setBelong(childList.get(k).getBelong());
                    kChildren.setCreateUserId(childList.get(k).getCreateUserId());
                    kChildren.setCreateTime(childList.get(k).getCreateTime());
                    kChildren.setCreateUserName(childList.get(k).getCreateUserName());
                    kChildren.setUpdateUserId(childList.get(k).getUpdateUserId());
                    kChildren.setUpdateTime(childList.get(k).getUpdateTime());
                    kChildren.setUpdateUserName(childList.get(k).getUpdateUserName());
                    kChildren.setOrgId(childList.get(k).getOrgId());
                    kChildren.setOrgCode(childList.get(k).getOrgCode());
                    kChildren.setDeptCode(childList.get(k).getDeptCode());
                    kChildren.setDeptName(childList.get(k).getDeptName());
                    kChildren.setDeptPath(childList.get(k).getDeptPath());
                    kChildren.setDeptLevel(childList.get(k).getDeptLevel());
                    kChildren.setDeptNodeCode(childList.get(k).getDeptNodeCode());
                    kChildren.setChildren(childList.get(k).getChildren() == null ? new ArrayList() : childList.get(k).getChildren());
                    kChildren.setLevel(childList.get(k).getLevel());
                    jChildrenList.add(kChildren);
                }
            }
            jChildren.setChildren(jChildrenList);
            resultList.add(jChildren);
        }

        return resultList;
    }

    public List<DingdingDeptTreeListQueryResp> getTreeList(DingdingDeptTreeListParamDTO requestDTO){

        requestDTO.check();

        // 查询数据集合
        List<DingdingDeptTreeQuery> dataList = dingdingDeptTreeMapper.getTreeList(requestDTO);

        // 组装数据
        List<DingdingDeptTreeListQueryResp> respList = new ArrayList<>();
        if(dataList != null && dataList.size() > 0){
            dataList.stream().forEach( x ->{
                DingdingDeptTreeListQueryResp item = new DingdingDeptTreeListQueryResp();
                item.setId(x.getId());
                item.setType(x.getType());
                item.setDeptCode(x.getDeptCode());
                item.setDeptName(x.getDeptName());
                item.setDeptPath(x.getDeptPath());
                item.setDeptLevel(x.getDeptLevel());
                item.setDeptNodeCode(x.getDeptNodeCode());
                item.setRemark(x.getRemark());
                item.setBelong(x.getBelong());
                item.setCreateUserId(x.getCreateUserId());
                item.setCreateUserName(x.getCreateUserName());
                item.setCreateTime(x.getCreateTime());
                item.setOrgId(x.getOrgId());
                item.setOrgCode(x.getOrgCode());
                item.setUpdateUserId(x.getUpdateUserId());
                item.setUpdateUserName(x.getUpdateUserName());
                item.setUpdateTime(x.getUpdateTime());
                item.setDel(x.getDel());
                item.setHasChildren(x.getHasChildren());
                item.setDeptNodeName(x.getDeptNodeName());
                item.setLevel(x.getLevel());
                respList.add(item);
            });
        }

        return respList;
    }

    /**
     * 通过部门编码，查询所有下级门店，包含本级
     * @param belong
     * @param deptCode
     * @return
     */
    public List<DingdingDeptTreeListResp> getDeepListByCode(String belong, String deptCode){
        // 查询数据集合
        List<DingdingDeptTree> dataList = dingdingDeptTreeMapper.getDeepListByCode(belong, deptCode);

        // 组装数据
        List<DingdingDeptTreeListResp> respList = new ArrayList<>();
        if(dataList != null && dataList.size() > 0){
            dataList.stream().forEach( x ->{
                DingdingDeptTreeListResp item = new DingdingDeptTreeListResp();
                item.setId(x.getId());
                item.setType(x.getType());
                item.setDeptCode(x.getDeptCode());
                item.setDeptName(x.getDeptName());
                item.setDeptPath(x.getDeptPath());
                item.setDeptLevel(x.getDeptLevel());
                item.setDeptNodeCode(x.getDeptNodeCode());
                item.setRemark(x.getRemark());
                item.setBelong(x.getBelong());
                item.setCreateUserId(x.getCreateUserId());
                item.setCreateUserName(x.getCreateUserName());
                item.setCreateTime(x.getCreateTime());
                item.setOrgId(x.getOrgId());
                item.setOrgCode(x.getOrgCode());
                item.setUpdateUserId(x.getUpdateUserId());
                item.setUpdateUserName(x.getUpdateUserName());
                item.setUpdateTime(x.getUpdateTime());
                item.setDel(x.getDel());
                respList.add(item);
            });
        }

        return respList;
    }

    public List<DingdingDeptTreeListResp> getList(DingdingDeptTreeListParamDTO requestDTO){

        requestDTO.check();

        // 查询数据集合
        List<DingdingDeptTree> dataList = dingdingDeptTreeMapper.getList(requestDTO);

        // 组装数据
        List<DingdingDeptTreeListResp> respList = new ArrayList<>();
        if(dataList != null && dataList.size() > 0){
            dataList.stream().forEach( x ->{
                DingdingDeptTreeListResp item = new DingdingDeptTreeListResp();
                item.setId(x.getId());
                item.setType(x.getType());
                item.setDeptCode(x.getDeptCode());
                item.setDeptName(x.getDeptName());
                item.setDeptPath(x.getDeptPath());
                item.setDeptLevel(x.getDeptLevel());
                item.setDeptNodeCode(x.getDeptNodeCode());
                item.setRemark(x.getRemark());
                item.setBelong(x.getBelong());
                item.setCreateUserId(x.getCreateUserId());
                item.setCreateUserName(x.getCreateUserName());
                item.setCreateTime(x.getCreateTime());
                item.setOrgId(x.getOrgId());
                item.setOrgCode(x.getOrgCode());
                item.setUpdateUserId(x.getUpdateUserId());
                item.setUpdateUserName(x.getUpdateUserName());
                item.setUpdateTime(x.getUpdateTime());
                item.setDel(x.getDel());
                respList.add(item);
            });
        }

        return respList;
    }

    public DingdingDeptTreeDetailResp getDetail(DingdingDeptTreeDetailParamDTO param) {

        DingdingDeptTree dbData = dingdingDeptTreeMapper.getDetail(param);
        if(dbData == null){
            return null;
        }

        DingdingDeptTreeDetailResp result = new DingdingDeptTreeDetailResp();
        result.setId(dbData.getId());
        result.setType(dbData.getType());
        result.setDeptCode(dbData.getDeptCode());
        result.setDeptName(dbData.getDeptName());
        result.setDeptPath(dbData.getDeptPath());
        result.setDeptLevel(dbData.getDeptLevel());
        result.setDeptNodeCode(dbData.getDeptNodeCode());
        result.setRemark(dbData.getRemark());
        result.setBelong(dbData.getBelong());
        result.setCreateUserId(dbData.getCreateUserId());
        result.setCreateUserName(dbData.getCreateUserName());
        result.setCreateTime(dbData.getCreateTime());
        result.setOrgId(dbData.getOrgId());
        result.setOrgCode(dbData.getOrgCode());
        result.setUpdateUserId(dbData.getUpdateUserId());
        result.setUpdateUserName(dbData.getUpdateUserName());
        result.setUpdateTime(dbData.getUpdateTime());
        result.setDel(dbData.getDel());
        return result;
    }

//    public void updateById(DingdingDeptTreeUpdateByIdParamDTO param) {
//        param.check();
//
//        DingdingDeptTreeDetailParamDTO queryDetailDTO = new DingdingDeptTreeDetailParamDTO();
//        queryDetailDTO.setId(param.getId());
//        DingdingDeptTree dbData = dingdingDeptTreeMapper.getDetail(queryDetailDTO);
//        if(dbData == null){
//            throw new DefaultException("更新的记录不存在");
//        }
//
//        dingdingDeptTreeMapper.updateById(param);
//    }

//    public void deleteById(DingdingDeptTreeDeleteByIdParamDTO paramDTO) {
//        paramDTO.check();
//        dingdingDeptTreeMapper.deleteById(paramDTO);
//    }

    public void add(DingdingDeptTreeAddParamDTO param) {
        param.setDel(0);
        param.setCreateTime(new Date());
        dingdingDeptTreeMapper.add(param);
    }

    public void batchAdd(List<DingdingDeptTreeAddParamDTO> dataList) {
        if(dataList == null || dataList.size() == 0){
            return;
        }

        for(DingdingDeptTreeAddParamDTO data : dataList){
            data.setDel(0);
            data.setCreateTime(new Date());
        }

        dingdingDeptTreeMapper.batchAdd(dataList);
    }

    public void deleteByBelong(String belong) {
        dingdingDeptTreeMapper.deleteByBelong(belong);
    }
}
